<?php

namespace IMT\SynchBundle\Controller;

use HWI\Bundle\OAuthBundle\OAuth\ResourceOwnerInterface;
use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken;
use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;

use HWI\Bundle\OAuthBundle\Controller\ConnectController as BaseController;

class ConnectController extends BaseController
{
    /**
     * Connects a user to a given account if the user is logged in and connect is enabled.
     *
     * @param Request $request The active request.
     * @param string  $service Name of the resource owner to connect to.
     *
     * @throws \Exception
     *
     * @return Response
     *
     * @throws NotFoundHttpException if `connect` functionality was not enabled
     * @throws AccessDeniedException if no user is authenticated
     */
    public function connectServiceAction(Request $request, $service)
    {
        $connect = $this->container->getParameter('hwi_oauth.connect');
        if (!$connect) {
            throw new NotFoundHttpException();
        }

        $user = $this->container->get('security.context')->getToken()->getUser();
        if (!$user) {
            throw new AccessDeniedException('Cannot connect an account.');
        }
        
        $accountId = $this->container->get('session')->get('imt_account_synch_id');
        if (!$accountId) {
        	throw new NotFoundHttpException('Compte introuvable');
        }
        
        // Get the data from the resource owner
        $resourceOwner = $this->getResourceOwnerByName($service);

        $session = $request->getSession();
        $key = $request->query->get('key', time());
        $accessToken = null;
            
        $em = $this->container->get('doctrine.orm.entity_manager');

        $account = $em->getRepository('IMTAccountBundle:AccountGmail')->find($accountId);
        
        if($account->getAccessToken()){
        	$accessToken = $account->getAccessToken();
        } else if($account->getRefreshToken()){
        	$account->setAccessToken(null);
        	$accessTokenResult = $resourceOwner->refreshAccessToken($account->getRefreshToken());
        	        	
        	if(is_array($accessTokenResult)){
        		$account = $this->hydrateAccountToken($account, $accessTokenResult);
        	} else {
        		throw new \Exception('Token invalide');
        	}
        	
        	$accessToken = $account->getAccessToken();
        	
        } else if ($resourceOwner->handles($request)) {
        	
        	$account->setAccessToken(null);
            $accessTokenResult = $resourceOwner->getAccessToken(
                $request,
                $this->generate('hwi_oauth_connect_service', array('service' => $service), true)
            );
            
            if(is_array($accessTokenResult)){
            	$account = $this->hydrateAccountToken($account, $accessTokenResult);
            } else {
            	throw new \Exception('Token invalide');
            }
            
            $accessToken = $account->getAccessToken();
        }
        
        $resourceOwner->getAccountInformation($accessToken, $account, $em);
        
        $resourceOwner->getEventInformation($accessToken, $account, $em, $this->container);
        
        $this->container->get('session')->set('imt_account_synch_id', null);
        
        try {
        	$response = $this->container->get('router')->generate($resourceOwner->getRedirect());
        	return new RedirectResponse($response);
        } catch(\Exception $e){
        	exit;
        }
        
        exit;
    }
    
    public function hydrateAccountToken($account, $token)
    {
    	$account->setAccessToken($token['access_token']);
    	$account->setRefreshToken(isset($token['refresh_token']) ? $token['refresh_token'] : null);
    	$account->setExpireIn($token['expires_in']);
    	
    	return $account;
    }
    
    /**
     * @param Request $request
     * @param string  $service
     *
     * @return RedirectResponse
     */
    public function redirectToServiceAction(Request $request, $service)
    {
    	// Check for a specified target path and store it before redirect if present
    	$param = $this->container->getParameter('hwi_oauth.target_path_parameter');
    
    	if (!empty($param) && $request->hasSession() && $targetUrl = $request->get($param, null, true)) {
    		$providerKey = $this->container->getParameter('hwi_oauth.firewall_name');
    		$request->getSession()->set('_security.' . $providerKey . '.target_path', $targetUrl);
    	}
    
    	return new RedirectResponse($this->container->get('hwi_oauth.security.oauth_utils')->getAuthorizationUrl($service));
    }
}

